package com.smart.thrift.config.client;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;

import java.util.*;

public class ThriftRefClientBeanScanProcessor implements ApplicationContextAware, BeanFactoryPostProcessor, EnvironmentAware,
        ResourceLoaderAware {

    private static final String DEFAULT_SCAN_PACKAGE = "";

    private ApplicationContext applicationContext;
    private Environment environment;
    private ResourceLoader resourceLoader;
    private final Set<String> packagesToScan;


    public ThriftRefClientBeanScanProcessor(String... packagesToScan) {
        this(Arrays.asList(packagesToScan));
    }

    public ThriftRefClientBeanScanProcessor(Collection<String> packagesToScan) {
        this(new LinkedHashSet<>(packagesToScan));
    }

    public ThriftRefClientBeanScanProcessor(Set<String> packagesToScan) {
        this.packagesToScan = packagesToScan;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        if (packagesToScan.isEmpty()) {
            Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(SpringBootApplication.class);
            String name = beansWithAnnotation.values().toArray()[0].getClass().getPackage().getName();
            packagesToScan.add(name + ".*");
        }
        BeanDefinitionRegistry definitionRegistry = (BeanDefinitionRegistry) beanFactory;
        ThriftRefClientBeanScanner beanScanner = new ThriftRefClientBeanScanner(definitionRegistry, applicationContext, environment, resourceLoader);
        beanScanner.setBeanNameGenerator(new AnnotationBeanNameGenerator());
        beanScanner.setScopedProxyMode(ScopedProxyMode.INTERFACES);
        beanScanner.scan(packagesToScan.isEmpty() ? new String[]{DEFAULT_SCAN_PACKAGE} : packagesToScan.toArray(new String[]{}));
    }
}
